﻿using System.Diagnostics;
using System.Reflection;

namespace zijian666.Core;

/// <summary>
/// 程序集描述
/// </summary>
public class AssemblyDescription
{
    private Type[]? _types;

    /// <summary>
    /// 构造函数
    /// </summary>
    public AssemblyDescription(Assembly assembly)
    {
        Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
        AssemblyName = assembly.GetName();
        try
        {
            Name = AssemblyName.Name;
        }
        catch (Exception e)
        {
            Exception = e;
        }
        try
        {
            FullName = assembly.FullName;
        }
        catch (Exception e)
        {
            Exception = e;
        }
        try
        {
            Location = assembly.Location;
        }
        catch (Exception e)
        {
            Exception = e;
        }
        try
        {
            IsDynamic = assembly.IsDynamic;
        }
        catch (Exception e)
        {
            Exception = e;
        }
    }
    /// <summary>
    /// 被描述的程序集
    /// </summary>
    public Assembly Assembly { get; }
    /// <summary>
    /// 程序集中的类
    /// </summary>
    public Type[] Types => _types ??= GetTypes();
    /// <summary>
    /// 程序集的名称
    /// </summary>
    public string? Name { get; }
    /// <summary>
    /// 程序集名称
    /// </summary>
    public AssemblyName? AssemblyName { get; }
    /// <summary>
    /// 程序集的完成名称
    /// </summary>
    public string? FullName { get; }
    /// <summary>
    /// 程序集路径
    /// </summary>
    public string? Location { get; }
    /// <summary>
    /// 是否是动态程序集
    /// </summary>
    public bool? IsDynamic { get; }
    /// <summary>
    /// 程序集在导出类型时是否存在异常
    /// </summary>
    public Exception? Exception { get; private set; }

    /// <summary>
    /// 查找程序集中的类
    /// </summary>
    private Type[] GetTypes()
    {
        if (_types != null)
        {
            return _types;
        }
        if (Assembly == null)
        {
            return Type.EmptyTypes;
        }
        try
        {
            return Assembly.GetTypes().Where(x => x is not null).ToArray();
        }
        catch (Exception ex)
        {
            Trace.TraceError("获取程序集中所有类型异常:" + ex.Message, ex);
            Exception = ex;
            return (ex as ReflectionTypeLoadException)?.Types.Where(x => x is not null).ToArray() ?? Type.EmptyTypes;
        }
    }

    /// <inheritdoc />
    public override bool Equals(object obj) => obj is AssemblyDescription desc && Equals(desc, this);

    /// <inheritdoc />
    public override int GetHashCode() => Assembly?.GetName()?.Name?.GetHashCode() ?? 0;

    /// <inheritdoc />
    public override string ToString() => "AssemblyDescription:" + Assembly.ToString();

    /// <inheritdoc />
    private static bool Equals(AssemblyDescription x, AssemblyDescription y)
    {
        if (ReferenceEquals(x.Assembly, y.Assembly))
        {
            return true;
        }

        if (x.IsDynamic is true || y.IsDynamic is true)
        {
            return false;
        }

        return string.Equals(x?.Location, y?.Location, StringComparison.OrdinalIgnoreCase) || string.Equals(x?.FullName, y?.FullName, StringComparison.Ordinal) || string.Equals(x?.Name, y?.Name, StringComparison.Ordinal);
    }
}
